package GUI_main;


/**
 *NOTE:
 *CLASS: TCPsvr_thread
 *
 * Brief description:
 * TCP server is the one who is listening at a port waiting for client to connect to it.
 * This is the multithread version, meaning it just take in the Socket instance that is already
 * connected (mySvrSocket.accept()). Use for listening socket
 *
 * HOW TO USE:
 * 1. To start listening to a port, just use the constructor and pass port number between 1025 to 65535
 *    E.g.
 *
 * 2. To send a string use send(String msg)
 *    E.g. myTCPsvr.send("Hello!");
 *
 * 3. To receive a msg from server
 *    E.g. String tempStr = myTCPsvr.rcv();
 *
 * 4. To disconnect i.e close socket.s
 *    E.g myTCPsvr.close();
 *
 *
 * @author Jianxin
 */


import java.io.*;
import java.net.*;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
//import java.util.Scanner;

public class TCPsvr_thread extends Thread{
        //I. <<Attributes>>
    public static String newline = System.getProperty("line.separator");
        private Socket connectionSocket;//socket used to TCP with client
        private List<String> msg_list;//contains list of msg to be send
        private BufferedReader inFromClient;//buffer for reading in client data
        private DataOutputStream outToClient;//buffer for output client data
        String myNick=new String();

        String passPhrase   = "My Pass Phrase";

        // Create encrypter/decrypter class//
        StringEncrypter desEncrypter = new StringEncrypter(passPhrase);

        //II.<<Contructor>>
            //Pre-condition: ServerSocket must be created! Port is already known in svrSocket
            //Post-condition: Server (i.e. this computer) starts to listen to the port specified in svrSocket
        public TCPsvr_thread(Socket connectionSocket,List<String> msg_list,String nick) throws Exception{
                this.myNick=nick;
                this.msg_list=msg_list;
                this.connectionSocket=connectionSocket;
                inFromClient= new BufferedReader(new InputStreamReader(connectionSocket.getInputStream()));
                outToClient= new DataOutputStream(connectionSocket.getOutputStream());
        }



	//III. <<Method>>
        //a. the Multithreaded msg

        public void run(){
            String rcv_str="IF YOU RECEIVE THIS MSG, THERE IS ERROR IN rcv() of TCPsvr_thread";
            String clientIP=getClientIP().substring(1);//substring to remove / e.g. /192.168.1.101, remove to become 192.168.1.101
            try{
                //keep looping to rcv data until go connection error!
                while(true){
                    String tempStr=rcv();

                    //if tempStr is null, TCP is terminated therefore break out of the while loop!
                    if(tempStr.equals(null)){
                        break;
                    }
                    //next check if target nick is the same as nick for this messenger.
                    //if same that means it is for this instance of messenger!
                    String[] tempArr=tempStr.split(":");
                    //tempArr[0]: Target Nick
                                                    //set the true to disable nickname check
                    if((tempArr[0].equals(myNick))||(true)){//if is for this messenger instance of the same nick...
                        //clip away the nick by removing the first array element!
                        tempStr="";
                        for(int i=1;i<tempArr.length;i++){
                            tempStr=tempStr+":"+tempArr[i];
                            if(i==1){//for first element we backspaced the ":"
                                tempStr=tempStr.substring(1);
                            }
                        }

                        // proceed as normal
                        rcv_str=clientIP+":"+tempStr;//add the IP address header to it

                        msg_list.add(rcv_str);//add to msg_list (note that this msg_list is know to chat_ctrl too)
                        System.out.println("--listen_controller received msg!: "+rcv_str);
                    }
                    else{
                        System.out.println("--listen_controller received msg! BUT NOT FOR this NICK! is for: "+tempArr[0]+"\n   msg is: "+tempStr);
                    }

                    
                }

                //once outside while loop, close thread
                this.close();

            }
            catch(Exception e){
                System.out.println("Error in run() of TCPsvr_thread. Thread close.");
                try {
                    close(); //close the port once error detect in TCP connection, e.g. TCP connection close peer
                } catch (Exception ex) {
                   System.out.println("Error in run()-catch of TCPsvr_thread. socket close error.Reason: "+ex.getLocalizedMessage());
                }
            }

        }

	//a. TCP receiving
            //Pre-condition: Client must be sending data, else function will simply keep looping and await the client data
            //Post-condition: Client msg is received and return as a String
	public String rcv() throws Exception{
            // return the String received from client.
            try{
                // Decrypt the string
					String tmp = inFromClient.readLine();
                    tmp=tmp.replace("......", newline);
					System.out.println("RCV: " + tmp);
					return desEncrypter.decrypt(tmp);
                //return inFromClient.readLine();//will wait at this step for msg to come in
            }
            catch(Exception e){
                System.out.println("TCP server receiving fail! Reason:"+e.toString());
                throw e;
            }

        }


        //b. TCP sending
            //Pre-condition: TCP connection must be established
            //Post-condition: Msg to be sent is sent
        public void send(String send_str) throws Exception{
            try{
            // Encrypt the string
                    String desEncrypted       = desEncrypter.encrypt(send_str);
					desEncrypted.replace(newline, "......");
                    outToClient.flush();
                    outToClient.writeBytes(desEncrypted+"\n");
					System.out.println("SEND: " + desEncrypted);
            }
            catch (Exception e){
                System.out.println("TCP server sending fail! Reason:"+e.toString());
                throw e;
            }
        }

        //c. TCP disconnecting
            //Pre-condition: TCP connection must be first established
            //Post-condition: TCP connection is disconnected. Function send() and rcv() can not be invoked!
        public void close() throws Exception{
            try{
                connectionSocket.close();
         //       svrSocket.close();
            }
            catch(Exception e){
                System.out.println("TCP Server closing socket fail! Reason:"+e.toString());
                throw e;
            }
        }


        //d. Return client IP
        public String getClientIP(){
            return connectionSocket.getInetAddress().toString();
        }

        /*
        //d. Check TCP status, return false if client disconnected and true if otherwise
            //Pre-condition: None
            //Post-condition: Return false if client disconnected and true if otherwise
        public boolean getStatus(){
            if (connectionSocket.isConnected())
                return true;
            else
                return false;
        }
        */
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
       //user info list    lubin.
       // UserInfo.txt
        
        public class UserInfo
        {

	            public void newfile() 
	            {
	
	              File f=new File("UserInfo.txt");
	              FileOutputStream fop=new FileOutputStream(f);
	            }
	            
            
	           // function to use to write to file
	           public void writeToFile(string instr)
	           {
	        	   InputStreamReader convert = new InputStreamReader(System.in);
	               BufferedReader stdin = new BufferedReader(convert);
	               File outfile = new File("UserInfo.txt");
	        	   
	               if (outfile.exists() )
	               {
		        	   FileWriter fout = new FileWriter("UserInfo.txt",append);
		               PrintWriter fileout = new PrintWriter(fout,true);
		            
		               
		               ////////////// still need to check if username is used
		               
		               
		               
		               fileout.println(instr);
		               fileout.flush();
		               fileout.close();
	               }
	            
	               else
	               {
	                   newfile();
	                   writeToFile(instr);
	                   
	               }
	            }
	           
	           
	           // verify whether a certain username exists
	           public boolean verifyUsername(string username);
	           {
	        	   
	           }
	           
	           //verify a username/passowrd combination
	           public boolean verifyAccount(string username, string password)
	           {
	        	   
	           }
	           
	           
	           //register a new user, return 1 if registration is successful
	           public boolean Register();
	           {
	           	// "please enter your username"
	           	
	           	// check username, if username already exists, enter another one
	           	
	           	// "Please enter password"
	           	
	           	// Writefile (username, password) into UserInfo
	           	
	           }
            
	           
        }
	          

       
